<!--
 * @Author: WuFeng <763467339@qq.com>
 * @Date: 2024-11-21 16:10:08
 * @LastEditTime: 2024-11-27 17:55:49
 * @LastEditors: WuFeng <763467339@qq.com>
 * @Description: 
 * @FilePath: \markdown-magic\src\pages\Pdf\page\entry\editor\setTemplete.vue
 * Copyright 版权声明
-->
<template>
  <div class="pageWrap">
    <div class="handleWrap">
      <a-space>
        <a-button type="primary" @click="handleGenerate">生成</a-button>
        <a-button type="primary" ghost @click="handleDownload">下载</a-button>
      </a-space>
    </div>
    <div class="mainWrap">
      <!-- 参数列表区 -->
      <div class="paramsListWrap">
        <h2 class="title">
          参数列表
        </h2>
        <ul>
          <li 
            v-for="(item, index) in formParamList" 
            :key="index" 
            @click="handleParamClick(index, item)"
            :class="{active: index === curParamIndex}"
          >
            {{ item.name }}
          </li>
        </ul>
      </div>
      <!-- pdf 文件展示区 -->
      <div class="pdfWrap" id="J_pdfWrap">
        <div 
          v-for="page in state.pdfPages" 
          :key="page" class="pageItem" 
          :id="`pageItem${page}`"
          @drop="listenParamDrop($event, page)"
          @dragover.prevent
        >
          <div :id="`textLayer${page}`" class="textLayer"></div>
          <div :id="`annotationsLayer${page}`" class="annotationsLayer"></div>
          <div class="pdfCanvasWrap">
            <canvas :id="`pdfCanvas${page}`" />
          </div>
          <div class="formParamWrap">
            <template 
              v-for="(item, index) in formParamList"
            >
              <div 
                :key="index"
                class="formParamItem" 
                v-if="item.pageNum === page"
                @click="handleParamClick(index, item)"
                :class="{active: index === curParamIndex}"
                :style="`width: ${item?.width}px;height:${item?.height}px;left: ${item?.x}px;top:${item?.y}px;`"
              >
                <!--  文本 -->
                <div 
                  class="formParamItemWrap" 
                  v-if="item.typeValue === 'text'"
                >
                  <a-input 
                    disabled
                    :value="item?.name"
                  >
                  </a-input>
                </div>
                <!--  单选 -->
                <div 
                  class="formParamItemWrap" 
                  v-if="item.typeValue === 'radio'"
                >
                  <a-radio-group disabled v-if="item?.options">
                    <a-radio 
                      v-for="(item1, index1) in item?.options" :key="index1" :value="item1?.value"
                      :style="{display: 'flex'}"
                    >
                      {{ item1?.label }}
                    </a-radio>
                  </a-radio-group>
                </div>
                <!--  多选 -->
                <div 
                  class="formParamItemWrap" 
                  v-if="item.typeValue === 'checkbox'"
                >
                  <a-checkbox-group disabled v-if="item?.options">
                    <a-checkbox 
                      v-for="(item1, index1) in item?.options" :key="index1" :value="item1?.value"
                      :style="{display: 'flex'}"
                    >
                      {{ item1?.label }}
                    </a-checkbox>
                  </a-checkbox-group>
                </div>
                <!--  主体名称 -->
                <div 
                  class="formParamItemWrap" 
                  v-if="item.typeValue === 'subjectName'"
                >
                  <a-input 
                    disabled
                    :value="item?.name"
                  >
                  </a-input>
                </div>
                <!--  身份证号 -->
                <div 
                  class="formParamItemWrap" 
                  v-if="item.typeValue === 'idCard'"
                >
                  <a-input 
                    disabled
                    :value="item?.name"
                  >
                  </a-input>
                </div>
                <!--  日期 -->
                <div 
                  class="formParamItemWrap" 
                  v-if="item.typeValue === 'date'"
                >
                  <a-date-picker disabled :value="``" :placeholder="item.name" />
                </div>
                <!--  电话号码 -->
                <div 
                  class="formParamItemWrap" 
                  v-if="item.typeValue === 'phone'"
                >
                  <a-input 
                    disabled
                    :value="item?.name"
                  >
                  </a-input>
                </div>
  
              </div>
            </template>
          </div>
        </div>
      </div>
      <!-- 右侧操作区 -->
      <div class="rightWrap">
        <div class="rightContent">
          <h2 class="title">
            参数库
          </h2>
          <ul class="paramList">
            <li 
              v-for="(item, index) in paramList" 
              :key="index"
              @dragstart="handleParamDragstart($event, item)"
              @dragend="handleParamDragend($event, item)"
              :draggable="true"
            >
              <div class="flag"></div>
              <div class="flagName">
                {{item.name}}
              </div>
            </li>
          </ul>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, defineEmits, computed, onMounted, nextTick } from 'vue'
import { message } from 'ant-design-vue'

import { PDFDocument, rgb } from 'pdf-lib'

import * as PDF from 'pdfjs-dist'
import * as workerSrc from 'pdfjs-dist/build/pdf.worker.min?url'

import $ from 'jquery'

import 'pdfjs-dist/web/pdf_viewer.css'

import download from 'downloadjs'
import { filename } from '@tauri-apps/plugin-window-state'

PDF.GlobalWorkerOptions.workerSrc = workerSrc.default

// const pdfPath = '/pdf.pdf'
// const pdfPath = '/pdf.form.pdf'
const pdfPath = '/example.pdf'

const state = reactive<any>({
  pdfPath, // 本地PDF文件路径放在/public中
  pdfPages: '', // 页数
  pdfWidth: '', // 宽度
  pdfSrc: '', // 地址
  pdfScale: 1.5, // 放大倍数
})
let pdfDoc: any = null
onMounted(() => {
  pdfWrapWidth.value = document.getElementById('J_pdfWrap').clientWidth
  formParamList.splice(0, formParamList.length)
  // 加载 PDF 文件
  loadFile(state.pdfPath)
})
function loadFile(url: string) {
  PDF.getDocument(url).promise.then((p: any) => {
    pdfDoc = p
    const { numPages } = p
    state.pdfPages = numPages
    nextTick(() => {
      renderPage(1) // 从第一页开始渲染
    })
  })
}
function renderPage(num: number) {
  pdfDoc.getPage(num).then(async (page: any) => {
    const canvas: any = document.getElementById(`pdfCanvas${num}`)
    const ctx = canvas.getContext('2d')
    const dpr = window.devicePixelRatio || 1
    const bsr
        = ctx.webkitBackingStorePixelRatio
        || ctx.mozBackingStorePixelRatio
        || ctx.msBackingStorePixelRatio
        || ctx.oBackingStorePixelRatio
        || ctx.backingStorePixelRatio
        || 1
    const ratio = dpr / bsr
    const viewport = page.getViewport({ scale: state.pdfScale })
    canvas.width = viewport.width * ratio
    canvas.height = viewport.height * ratio
    canvas.style.width = '100%'
    canvas.style.height = '100%'
    state.pdfWidth = `${viewport.width}px`
    ctx.setTransform(ratio, 0, 0, ratio, 0, 0)
    // 将 PDF 页面渲染到 canvas 上下文中
    const renderContext = {
      canvasContext: ctx,
      viewport,
    }
    // page.render(renderContext)
    await page.render(renderContext)

    // // 添加文字层
    // const textContent = await page.getTextContent()
    // const textLayer = new PDF.TextLayer({
    //   textContentSource: textContent,
    //   viewport,
    //   container: document.getElementById('textLayer' + num),
    // })
    // await textLayer.render()

    // 添加注释层
    const annotationsContainer = document.getElementById('annotationsLayer' + num)
    annotationsContainer.innerHTML = '' // Clear the previous annotations
    page.getAnnotations().then((annotations) => {
      annotations.forEach((annotation, index) => {
        console.log('------------------------')
        console.log(`🚀 ~ annotations.forEach ~ annotation:`, annotation)
        // 过滤出表单字段（subtype 为 'Widget'）
        if (annotation.subtype === 'Widget' && annotation.fieldName) {
          const fieldName = annotation.fieldName
          // 当前页的实际宽高
          console.log(`🚀 ~ annotations.forEach ~ page:`, viewport)
          // // 缩放比例
          let _scale = Math.floor((pdfWrapWidth.value / viewport.viewBox[2] ) * 100) / 100
          console.log(`🚀 ~ annotations.for---------Each ~ _scale:`, _scale)
          const { x, y } = convertToCanvasCoordinates(
            annotation.rect[0],
            annotation.rect[1],
            viewport.viewBox[3],
            _scale
          )
          console.log(`🚀 ~ annotations.forEach ~ x:`, x)
          console.log(`🚀 ~ annotations.forEach ~ y:`, y)
          // 获取表单字段的位置和大小
          const item = {
            // 所在页码 1、2、3...
            pageNum: num,
            // 位置
            x,
            y: y - ((annotation.rect[3] - annotation.rect[1]) * _scale),
            // 宽高
            width: (annotation.rect[2] - annotation.rect[0]) * _scale,
            height: (annotation.rect[3] - annotation.rect[1]) * _scale,
            // 值
            value: '',
            // 名称
            name: `text${index}`,
            // 类型
            typeName: '',
            typeValue: '',
            // 选项  单选、多选
            options: [],
            // 拖拽来源于哪个区域 ： center ： 中间区域拖拽 ， right ： 右侧区域拖拽
            dragSource: 'auto'
          }
          if (annotation.fieldType === 'Tx' || fieldName.indexOf('text') > -1 || fieldName.indexOf('subjectName') > -1 || fieldName.indexOf('idCard') > -1 || fieldName.indexOf('date') > -1 || fieldName.indexOf('phone') > -1) {
            item.typeValue = 'text'
            item.typeName = '文本'
            item.name = `${fieldName}`
          }
          if (fieldName.indexOf('radio') > -1) {
            item.typeValue = 'radio'
            item.typeName = '单选'
            item.name = `${fieldName}`
            item.options = [
              { label: '是', value: '1' },
              { label: '否', value: '0' }
            ]
          }
          if (fieldName.indexOf('checkbox') > -1) {
            item.typeValue = 'checkbox'
            item.typeName = '多选'
            item.name = `${fieldName}`
            item.options = [
              { label: '你', value: '1' },
              { label: '我', value: '0' }
            ]
          }
          formParamList.push(item)
          
          return
          const rect = annotation.rect;
          const transformedRect = viewport.convertToViewportRectangle(rect)
          const annotationElement = document.createElement('div')
          annotationElement.style.position = 'absolute'
          annotationElement.style.left = `${transformedRect[0]}px`
          annotationElement.style.top = `${transformedRect[1]}px`
          annotationElement.style.width = `${transformedRect[2] - transformedRect[0]}px`
          annotationElement.style.height = `${transformedRect[3] - transformedRect[1]}px`
          annotationElement.style.border = '1px dashed blue'
          annotationElement.style.backgroundColor = 'rgba(255, 255, 0, 0.9)'
          annotationElement.style.pointerEvents = 'auto'
          annotationElement.title = JSON.stringify(annotation, null, 2) // Show annotation details on hover
          annotationsContainer.appendChild(annotationElement)
        }
      })
      console.log(`🚀 ~ annotations.forEach ~ formParamList:`, formParamList)
    })

    if (state.pdfPages > num)
      renderPage(num + 1)
  })
}

// 生成
const handleGenerate = async () => {
  // 获取pdf 对象
  const pdfLibDoc = await PDFDocument.load(await pdfDoc.getData())
  console.log(`🚀 ~ handleGenerate ~ pdfWrapWidth.value:`, pdfWrapWidth.value)
  const form = pdfLibDoc.getForm()
  // 遍历pdf所有页
  for (let num = 1; num <= pdfLibDoc.getPageCount(); num++) {
    // 获取当前页
    const page = pdfLibDoc.getPages()[num - 1]
    // 当前页的实际宽高
    const { width: pdfWidth, height: pdfPageHeight } = page.getSize();
    // 缩放比例
    const scale = Math.floor((pdfWidth / pdfWrapWidth.value) * 100) / 100
    console.log(`🚀 ~ handleGenerate ~ scale:`, scale)
    formParamList.forEach((rect, index) => {
      if (rect.pageNum !== num) {
        return
      }
      const x = Math.floor(rect.x * scale)
      const width = Math.floor(rect.width * scale)
      const height = Math.floor(rect.height * scale)
      
      const y = Math.floor((pdfPageHeight - rect.y * scale - height))

      const flag = rect.typeValue + index + 1

      // 文本、主体名称、身份证号、日期、电话号码
      if (rect.typeValue === 'text' || rect.typeValue === 'subjectName' || rect.typeValue === 'idCard' || rect.typeValue === 'date' || rect.typeValue === 'phone') {
        const field = form.createTextField(`${flag}`)
        // field.setText(`${flag}`);
        const curData = {
          x,  // 使用缩放后的X坐标
          y,  // 使用调整后的Y坐标
          width,  // 使用缩放后的宽度
          height,  // 使用缩放后的高度
          // backgroundColor: rgb(0.95, 0.95, 0.95),
          // borderColor: rgb(1, 1, 1),
          // borderWidth: 1
          // backgroundColor: 'n',
          // borderColor: 'n',
          borderWidth: 0
        }
        field.addToPage(page, curData)
      }

      // 单选
      if (rect.typeValue === 'radio') {
        const field = form.createRadioGroup(`${flag}`)
        field.addOptionToPage('你说谁', page, {
          x,
          y,
          borderWidth: 1,
          // borderColor: rgb(0, 0, 0),
          // backgroundColor: rgb(0, 0, 0),
          // textColor: rgb(0, 0, 0),
          width: 16,
          height: 16,
          hidden: true
        })
      }

      // 多选
      if (rect.typeValue === 'checkbox') {
        const field = form.createCheckBox(`${flag}`)
        field.addToPage(page, {
          x,
          y,
          width: 16,
          height: 16,
          hidden: true
        })
      }

    })
  }

  const pdfBytes = await pdfLibDoc.save()
  console.log(`🚀 ~ handleGenerate ~ pdfBytes:`, pdfBytes)
  download(pdfBytes, 'download.pdf', 'application/pdf')
}

// 下载
const handleDownload = () => {
}

// 参数库
const paramList = reactive([
  {
    value: 'text',
    name: '文本'
  },
  {
    value: 'radio',
    name: '单选'
  },
  {
    value: 'checkbox',
    name: '多选'
  },
  {
    value: 'subjectName',
    name: '主体名称'
  },
  {
    value: 'idCard',
    name: '身份证号'
  },
  {
    value: 'date',
    name: '日期'
  },
  {
    value: 'phone',
    name: '电话号码'
  }
])

// 当前拖拽操作的组件的数据
const dragParamDefault = {
  // 所在页码 1、2、3...
  pageNum: 0,
  // 位置
  x: 0,
  y: 0,
  // 宽高
  width: 200,
  height: 32,
  // 值
  value: '',
  // 名称
  name: '',
  // 类型
  typeName: '',
  typeValue: '',
  // 选项  单选、多选
  options: [],
  // 拖拽来源于哪个区域 ： center ： 中间区域拖拽 ， right ： 右侧区域拖拽
  dragSource: 'right'
}
let dragParam = reactive(dragParamDefault)

// pdf 展示区宽度
const pdfWrapWidth = ref(0)

// 拖拽出来的组件
const formParamList = reactive([])

// 监听参数拖拽到pdf页区域
const listenParamDrop = (event, page) => {
  dragParam = {
    ...dragParam,
    ...{ offsetX: event.offsetX, offsetY: event.offsetY },
    ... { x: event.offsetX, y: event.offsetY },
    pageNum: page,
    // name: `参数${formParamList.length + 1}`,
    name: `${dragParam.typeValue}${formParamList.length + 1}`,
    options: dragParam.typeValue === 'radio' || dragParam.typeValue === 'checkbox' ? [{
      value: '1',
      label: '选项1'
    }, {
      value: '2',
      label: '选项2'
    }] : []
  }
  formParamList.push(dragParam)
  console.log(`🚀 ~ listenParamDrop ~ formParamList:`, formParamList)
}

// 监听参数拖拽开始
const handleParamDragstart = (e, item) => {
  // console.log(`🚀 ~ handleParamDragstart ~ event:`, event)
  dragParam = {
    ...dragParamDefault,
    ...{ offsetX: e.offsetX, offsetY: e.offsetY },
    ...{ typeName: item.name, typeValue: item.value },
    dragSource: 'right'
  }
}

// 监听参数拖拽结束
const handleParamDragend = (event, item) => {
  // console.log(`🚀 ~ handleParamDragend ~ event:`, event)
  dragParam = {}
}

// 当前选中的参数的索引
const curParamIndex = ref(-1)
// 点击参数
const handleParamClick = (index, item) => {
  console.log(`🚀 ~ handleParamClick ~ index:`, index)
  curParamIndex.value = index
}

// 计算PDF坐标
const convertToCanvasCoordinates = (
  pdfX: number,
  pdfY: number,
  pageHeight: number,
  scale: number
) => {
  const adjustedPdfY = pageHeight - pdfY // 将 PDF 坐标系转换为 canvas 坐标系
  const canvasX = pdfX * scale
  const canvasY = adjustedPdfY * scale
  return { x: canvasX, y: canvasY }
}

</script>

<style lang="scss" scoped>
</style>
<style lang="scss" scoped>
.pageWrap{
  .handleWrap{
    padding: 0 12px 12px 12px;
    display: flex;
    justify-content: flex-end;
  }
  .mainWrap{
    display: flex;
    max-height: calc(100vh - 76px);
    .paramsListWrap{
      width: 250px;
      margin-right: 16px;
      background-color: #fff;
      padding: 0 12px;
      h2.title{
        border-bottom: 1px solid #d4d2d2;
        font-size: 16px;
        padding: 12px 0;
        font-weight: bold;
      }
      ul{
        max-height: calc(100vh - 76px - 76px);
        overflow-y: auto;
        li{
          background: #F7F7F7;
          border-radius: 3px;
          height: 36px;
          line-height: 36px;
          padding: 0 12px;
          margin-bottom: 12px;
          cursor: pointer;
          border: 1px solid #F7F7F7;
          overflow: hidden;
          &.active{
            background: #F2F8FF;
            border: 1px solid #216DFF;
          }
        }
      }

    }
    .pdfWrap{
      flex: 1;
      overflow-y: auto;
      .pageItem{
        position: relative;
        border: 1px solid #d4d2d2;
        margin-bottom: 12px;
        overflow: hidden;
        .textLayer,
        .annotationsLayer{
          position: absolute;
          left: 0;
          right: 0;
          top: 0;
          bottom: 0;
          // pointer-events: none;
          // width: 100%;
          // height: 100%;
        }
        .pdfCanvasWrap{
          width: 100%;
          height: 100%;
        }
        .formParamWrap{
          position: absolute;
          top: 0;
          right: 0;
          bottom: 0;
          left:0;
          z-index: 3;
          .formParamItem{
            position: absolute;
            border: 1px solid #d9d9d9;
            overflow: hidden;
            &.active{
              border: 1px solid #216DFF;
            }
            &::before{
              content: ' ';
              display: block;
              position: absolute;
              left: 0;
              top: 0;
              right: 0;
              bottom: 0;
              background-color: transparent;
              z-index: 1;
            }
            .formParamItemWrap{
              width: 100%;
              height: 100%;
              .ant-input{
                line-height: normal;
                height: 100%;
                border: none;
                padding: 0;
              }
            }
          }
        }
      }
    }
    .rightWrap{
      width: 350px;
      margin-left: 16px;
      background-color: #fff;
      overflow-y: auto;
      .rightContent{
        padding: 0 12px;
        h2.title{
          border-bottom: 1px solid #d4d2d2;
          font-size: 16px;
          padding: 12px 0;
          font-weight: bold;
        }
        .paramList{
          display: grid;
          gap: 12px;
          grid-template-columns: repeat(5, 1fr);
          // grid-template-columns: repeat(auto-fill,minmax(285px,1fr));
          justify-content: space-evenly;
          li{
            text-align: center;
            .flag{
              height: 40px;
              background-color: #F3F3F3;
              border-radius: 2px;
              cursor: move;
            }
            .flagName{
              font-size: 12px;
              padding: 12px 0 4px;
            }
          }
        }
      }
    }
  }
}
</style>